package org.bing.balancer;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.bing.balancer.impl.proxy.HexDumpProxy;
import org.bing.engine.common.logging.Log;
import org.bing.engine.common.logging.LogFactory;
import org.bing.engine.utility.helper.JdkDomHelper;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.w3c.dom.Element;

public class NettyBaseBalancer {
    protected static Log logger = LogFactory.getLog(NettyBaseBalancer.class);

    private static void clean(Server server) {
        try {
            server.stop();
        } catch (Exception e) {
            logger.error("Fail to stop jetty!", e);
            server.destroy();
        }
    }

    private static void sleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            // ignore
        }
    }

    private static void startAdmin(Server server) {
        try {
            HandlerWrapper context = new HandlerWrapper() {
                @Override
                public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
                        ServletException {
                    response.getWriter().println("<h1>Hello world!" + new java.util.Date() + "</h1>");
                    response.flushBuffer();
                }
            };

            server.setHandler(context);
            server.start();
        } catch (Throwable t) {
            logger.error("Fail to run balancer admin!", t);
            clean(server);
            sleep(3000);
        }
    }

    private static void startBalancer(String addr, int port) {
        HexDumpProxy proxy = new HexDumpProxy(addr, port);
        proxy.start();
    }

    /** balnacer Skeleton, simple admin for balnacer */
    public static void main(String[] args) throws Exception {
        Thread.currentThread().setName("bing-balancer-main");
        if (args == null || args.length == 0) {
            logger.warn("Balancer conf is null, use default! B *:80, A *:8080 ");
        }
        Element root = JdkDomHelper.build(new FileInputStream(args[0])).getDocumentElement();
        String address = JdkDomHelper.getSingleSubTextByName(root, "address", null);
        String port = JdkDomHelper.getSingleSubTextByName(root, "port", null);
        String adminPort = JdkDomHelper.getSingleSubTextByName(root, "adminPort", null);
        String address2 = address == null ? "*" : address;
        logger.info("Ready to start proxy " + address2 + ":" + port + "," + address2 + ":" + adminPort);
        // init admin server
        Server server = null;
        if (address == null) {
            server = new Server(Integer.parseInt(adminPort));
        } else {
            InetSocketAddress addr = new InetSocketAddress(address, Integer.parseInt(adminPort));
            server = new Server(addr);
        }
        while (true) {
            // TODO impl balancer upgrade, health check etc

            if (!server.isStarting() && !server.isStarted()) {
                // start admin server
                startAdmin(server);
            }
            if (server.isStarted()) {
                // start balancer
                startBalancer(address, Integer.getInteger(port));
            }
            sleep(5000);
        }
    }
}
